﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;

namespace WpfHardCodedStringsFinder
{
	public static class VisualExtension
	{
		public static T FindVisualParent<T>(UIElement element) where T : UIElement
		{
			UIElement parent = element;
			while (parent != null)
			{
				T correctlyTyped = parent as T;
				if (correctlyTyped != null)
				{
					return correctlyTyped;
				}
				parent = VisualTreeHelper.GetParent(parent) as UIElement;
			}
			return null;
		}

		public static T FindVisualParent<T>(UIElement element, int level) where T : UIElement
		{
			UIElement parent = element;
			int lev = 0;
			while (parent != null || level == lev)
			{
				T correctlyTyped = parent as T;
				if (correctlyTyped != null)
				{
					return correctlyTyped;
				}
				parent = VisualTreeHelper.GetParent(parent) as UIElement;
				lev++;
			}
			return null;
		}

		public static T FindChild<T>(DependencyObject parent) where T : DependencyObject
		{
			if (parent == null) return null;

			T childElement = null;
			int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
			for (int i = 0; i < childrenCount; i++)
			{
				var child = VisualTreeHelper.GetChild(parent, i);
				T childType = child as T;
				if (childType == null)
				{
					childElement = FindChild<T>(child);
					if (childElement != null) break;
				}
				else
				{
					childElement = (T)child;
					break;
				}
			}
			return childElement;
		}

		/// <summary> 
		/// Finds a Child of a given item in the visual tree.  
		/// </summary> 
		/// <param name="parent">A direct parent of the queried item.</param> 
		/// <typeparam name="T">The type of the queried item.</typeparam> 
		/// <param name="childName">x:Name or Name of child. </param> 
		/// <returns>The first parent item that matches the submitted type parameter.  
		/// If not matching item can be found, a null parent is being returned.
		/// </returns> 
		public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
		{
			// Confirm parent and childName are valid.   
			if (parent == null) return null; T foundChild = null;
			int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
			for (int i = 0; i < childrenCount; i++)
			{
				var child = VisualTreeHelper.GetChild(parent, i);
				// If the child is not of the request child type child    
				T childType = child as T;
				if (childType == null)
				{
					// recursively drill down the tree   
					foundChild = FindChild<T>(child, childName);
					// If the child is found, break so we do not overwrite the found child.  
					if (foundChild != null) break;
				}
				else if (!string.IsNullOrEmpty(childName))
				{
					var frameworkElement = child as FrameworkElement;
					// If the child's name is set for search     
					if (frameworkElement != null && frameworkElement.Name == childName)
					{
						// if the child's name is of the request name       
						foundChild = (T)child; break;
					}
				}
				else
				{
					// child element found.     
					foundChild = (T)child;
					break;
				}
			} return foundChild;
		}
	}
}
